/**
 * 跨操作系统统一接口 公共基础实现
 */
 
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "unios.h"

void* unios_malloc0(size_t size) {
	void* mem = unios_malloc(size);
	return mem ? memset(mem, 0, size) : NULL;
}

extern void* mcu_get_pointer(const void *stream);

void* unios_get_pointer(const void *stream) {
    return mcu_get_pointer(stream);
}

unios_us_t unios_us_elapsed(unios_us_t earlier_time_us) {
	unios_us_t now = unios_us_now();
    if(now < earlier_time_us) return UINT64_MAX - earlier_time_us + now;
    return now - earlier_time_us;
}

unios_ms_t unios_ms_elapsed(unios_ms_t earlier_time_ms) {
	unios_ms_t now = unios_ms_now();
    if(now < earlier_time_ms) return UINT64_MAX - earlier_time_ms + now;
    return now - earlier_time_ms;
}

unios_sec_t unios_rtcsec_elapsed(unios_sec_t earlier_time_sec) {
    unios_sec_t now = unios_rtcsec_get();
    if(now < earlier_time_sec) return UINT64_MAX - earlier_time_sec + now;
    return now - earlier_time_sec;
}

std_err_t unios_file_save(const char *filepath, const void *mem, size_t size) {
	if(!filepath || !mem || !size) return STD_ERR_INVALID_ARG;
	unios_file_t uf;
	std_err_t err = unios_file_open(filepath, UNIOS_FILE_OFLAG_WRITE_TRUNCATE, &uf);
	if(err || !unios_file_is_valid(uf)) return STD_ERR_NOT_FOUND;
	err = unios_file_write(uf, mem, size, 0, NULL);
	unios_file_close(uf);
	return err;
}

std_err_t unios_file_load(const char *filepath, void **mem, size_t *size) {
	if(!filepath || !mem) return STD_ERR_INVALID_ARG;
	*mem = NULL; if(size) *size = 0;
	void *buf = NULL;

	unios_file_t uf;
	std_err_t err = unios_file_open(filepath, UNIOS_FILE_OFLAG_READ, &uf);
	if(err || !unios_file_is_valid(uf)) return STD_ERR_NOT_FOUND;

	do {
		int64_t fsize = unios_file_datasize(uf);        if(fsize < 1) { err = STD_ERR_INVALID_SIZE; break; }
		buf = malloc(fsize);                            if(!buf) { err = STD_ERR_NO_MEM; break; }
		size_t len = 0;
		err = unios_file_read(uf, buf, fsize, 0, &len);	if(err) { break; }
		*mem = buf; if(size) *size = len;
	} while(0);

	unios_file_close(uf);
	if(err && buf) free(buf);
	return err;
}
